package cn.schoolwow.quickserver.server;

import cn.schoolwow.quickserver.domain.Client;
import cn.schoolwow.quickserver.domain.ServerConfigMeta;
import cn.schoolwow.quickserver.exception.HttpStatusException;
import cn.schoolwow.quickserver.handler.Handler;
import cn.schoolwow.quickserver.handler.HttpRequestHandler;
import cn.schoolwow.quickserver.handler.HttpResponseHandler;
import cn.schoolwow.quickserver.util.ExceptionHandlerUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
import java.util.List;

/**
 * 客户端线程
 * */
public class HttpClientThread implements Runnable{
    private Logger logger = LoggerFactory.getLogger(HttpClientThread.class);

    /**
     * 客户端Socket
     * */
    private Socket socket;

    /**
     * 服务端配置信息
     * */
    private ServerConfigMeta serverConfigMeta;

    public HttpClientThread(Socket socket, ServerConfigMeta serverConfigMeta) {
        this.socket = socket;
        this.serverConfigMeta = serverConfigMeta;
    }

    @Override
    public void run() {
        Client client = new Client();
        client.socket = socket;
        client.serverConfigMeta = this.serverConfigMeta;
        while(true){
            client.lastActiveTime = System.currentTimeMillis();
            client.reset();
            client.httpRequestMeta.remoteAddress = client.socket.getInetAddress();
            try {
                client.httpRequestMeta.inputStream = client.socket.getInputStream();
                client.httpResponseMeta.outputStream = client.socket.getOutputStream();
                Handler handler = new HttpRequestHandler();
                while (null != handler) {
                    handler = handler.handle(client);
                }
                if(shouldCloseSocket(client)){
                    client.socket.close();
                    break;
                }
            } catch (Exception e){
                ExceptionHandlerUtil.handleExceptionHandler(client,e);
                try {
                    new HttpResponseHandler().handle(client);
                } catch (IOException ex) {
                    if((e instanceof SocketException)||(e instanceof HttpStatusException)){
                        logger.debug("[链接异常]{},套接字:{}",e.getMessage(),socket);
                    }else{
                        ex.printStackTrace();
                    }
                    try {
                        if(!socket.isClosed()){
                            socket.close();
                        }
                    } catch (IOException ex1) {
                        ex1.printStackTrace();
                    }
                }
                break;
            }
        }
    }

    /**
     * 是否应该关闭Socket链接
     * */
    private boolean shouldCloseSocket(Client client){
        if(!client.serverConfigMeta.keepAlive){
            return true;
        }
        List<String> connectionHeader =  client.httpRequestMeta.headers.get("Connection");
        if(null!=connectionHeader&&connectionHeader.size()>0){
            if(connectionHeader.get(0).equalsIgnoreCase("close")){
                logger.debug("[客户端主动关闭链接]Connection:{}",connectionHeader.get(0));
                return true;
            }
        }
        return false;
    }
}
